home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyo (Python 2.5) import common import contacts from util import Storage, to_storage, dyn_dispatch, tag, odict, threaded, urlcacheopen, cproperty, get from util.observe import ObservableProperty from common.sms import validate_sms, normalize_sms from util.callbacks import callsback from MSNUtil import url_decode import time import datetime import logging log = logging.getLogger('msn.buddy') yesterday = lambda : datetime.datetime.today() - datetime.timedelta(1) import sys thismod = sys.modules[__name__] del sys try: _ except: _ = lambda s: s statuses = Storage(brb = _('Be Right Back'), phone = _('On the Phone'), lunch = _('Out to Lunch')) class MSNBuddy(common.buddy): __slots__ = '\n status_message\n msn_obj\n _idle_start\n pending_auth\n phone_home\n phone_work\n phone_mobile\n allow_mobile\n enable_wireless\n remote_alias\n has_blog\n client_id\n role_ids\n get_profile\n _space\n membersoap\n contactsoap\n '.split() def __init__(self, msn, name = None): self._status = 'unknown' self._status_message = '' self._got_presence = False self.phone_home = None self.phone_work = None self.phone_mobile = None self.allow_mobile = None self.enable_wireless = None self.remote_alias = None self.has_blog = None self.msn_obj = None self._idle_start = 0 self.info = { } self.role_ids = { } self.pending_auth = False common.buddy.__init__(self, url_decode(name), msn) if self is self.protocol.self_buddy: profile = profile import common profile.account_manager.buddywatcher.unregister(self) self.CID = 0 self.space = None if self._space: try: self.update_contact_card(tag(self._space)) self._space = None self.mships = { } self.contactsoap = None self.membersoap = None self._btype = 'im' def __hash__(self): return common.buddy.__hash__(self) def sms(self): if validate_sms(self.phone_mobile): return self.phone_mobile else: return False sms = property(sms) def _get_phone_mobile(self): return getattr(self, '_phone_mobile', None) def _set_phone_mobile(self, val): if val and val.startswith('tel:'): val = val[4:] self._phone_mobile = val phone_mobile = property(_get_phone_mobile, _set_phone_mobile) def id(self): if self.contactsoap is not None: v = self.contactsoap.ContactId if v: return v if not self.guid: pass return self.name id = property(id) def _get_guid(self): return getattr(self, '_guid', None) def _set_guid(self, val): if not isinstance(val, self.protocol.ns.cid_class): raise TypeError('Was expecting type %r for guid, got %r (type=%r)', self.protocol.cid_class, val, type(val)) self._guid = val guid = property(_get_guid, _set_guid, doc = 'Contact ID, which takes the form of a UUID in modern versions of MSNP.In the past, it was simply the passport name of the contact.') def get_caps(self): caps = caps import common if self.status == 'mobile': return set([ caps.SMS, caps.EMAIL]) else: buddy_caps = set(self.protocol.caps) if not self.online: buddy_caps.discard(caps.FILES) return buddy_caps caps = property(get_caps) def _set_contactsoap(self, val): self._contactsoap = val if self.contactsoap is not None: phs = self.contactsoap.ContactInfo.Phones if phs is not None and phs.ContactPhone is not None: for phone in phs.ContactPhone: if phone.ContactPhoneType == 'ContactPhoneMobile': try: num = normalize_sms(phone.Number) except: continue if not validate_sms(num): continue self.phone_mobile = num continue def _get_contactsoap(self): return self._contactsoap contactsoap = property(_get_contactsoap, _set_contactsoap) def online(self): return self.status not in ('offline', 'unknown') online = property(online) def set_status(self, newval): oldstatus = self._status self._status = newval if oldstatus != newval and self._got_presence: self.notify('status', oldstatus, newval) def get_status(self): if not self._got_presence: return 'unknown' if self._status == 'idle': return 'idle' if self.away: return 'away' if self.mobile: return 'mobile' return self._status status = ObservableProperty(get_status, set_status, observe = ('_status',)) def profile(self): pass profile = property(profile) def away(self): return self._status in ('busy', 'brb', 'away', 'phone', 'lunch') away = property(away) def blocked(self): return self in self.protocol.block_list blocked = property(blocked) def stripped_msg(self): return self.status_message stripped_msg = property(stripped_msg) def _set_status_message(self, val): self._got_presence = True self._status_message = val def _get_status_message(self): return self._status_message status_message = property(_get_status_message, _set_status_message) def mobile(self): if self.sms or self.allow_mobile == 'Y': pass return self._status not in ('available', 'idle', 'available') mobile = property(mobile) def get_profile(self): self.protocol.get_profile(self) get_profile = common.action((lambda self: True))(get_profile) def sightly_status(self): if self.status == 'mobile': return _('Mobile') else: return statuses.get(self._status, self._status.title()) sightly_status = property(sightly_status) def block(self, _block = True, callback = None): self.protocol.block_buddy(self, _block, callback = callback) block = callsback(block) def unblock(self, callback = None): self.protocol.block_buddy(self, False, callback = callback) unblock = callsback(unblock) def service(self): num_or_str = get(self, '_btype', 1) num = get(dict(msn = 1, mob = 4, fed = 32), num_or_str, num_or_str) if num == 32 and self.name.endswith('yahoo.com'): prot_name = 'yahoo' else: prot_name = self.protocol.name return prot_name service = property(service) def __repr__(self): return '<MSNBuddy %s>' % self.name def __str__(self): return repr(self) def get_idle(self): return self.status == 'idle' def set_idle(self, val): pass idle = ObservableProperty(get_idle, set_idle, observe = ('status',)) def update(self, new): if not new: return None for field in new.__dict__: newval = getattr(new, field) if newval: setattr(self, field, newval) self.setnotifyif() continue def update_contact_card(self, card): if not card: return None self._space = card._to_xml(pretty = False) self.space = MSNSpace(self, card) def _update_ccard_elt(self, elt, kind): return dyn_dispatch(self, '_update_ccard_%s' % kind.lower(), elt) def _update_ccard_spacetitle(self, elt): self.space.update((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) def _update_ccard_album(self, elt): photos = [] for subel in elt: if subel._attrs.get('type', '') == 'Photo': photos.append(Storage((lambda .0: for e in .0: (e._name, e._cdata))(subel))) continue album = self.space.setdefault('album', Storage()) album.update((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) album.photos = photos _space = cproperty('') def _update_ccard_musiclist(self, elt): musiclist = self.space.setdefault('musiclist', Storage()) songs = [] for song in elt: if song._attrs.get('type', '') == 'MusicListEntry': songs.append(Storage((lambda .0: for e in .0: (e._name, e._cdata))(song))) continue musiclist.update((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) musiclist.songs = songs def _update_ccard_booklist(self, elt): booklist = self.space.setdefault('booklist', Storage()) books = [] for book in elt: if book._attrs.get('type', '') == 'BookListEntry': books.append(Storage((lambda .0: for e in .0: (e._name, e._cdata))(book))) continue booklist.update((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) booklist.books = books def _update_ccard_genericlist(self, elt): gen_lists = self.space.setdefault('gen_lists', []) entries = [] for entry in elt: if entry._attrs.get('type', '') == 'GenericListEntry': entries.append(Storage((lambda .0: for e in .0: (e._name, e._cdata))(entry))) continue new_list = Storage((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) new_list.entries = entries gen_lists.append(new_list) def _update_ccard_blog(self, elt): blog = self.space.setdefault('blog', Storage()) posts = [] for post in elt: if post._attrs.get('type', '') == 'Post': posts.append(Storage((lambda .0: for e in .0: (e._name, e._cdata))(post))) continue blog.update((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) blog.posts = posts def _update_ccard_profile(self, elt): profiles = self.space.setdefault('profiles', Storage()) for profile in elt: p_type = profile._attrs.get('type', '') if p_type.endswith('Profile'): prof = profiles.setdefault(p_type.lower()[:-7], Storage()) prof.update((lambda .0: for e in .0: (e._name, e._cdata))(profile)) continue profiles.update((lambda .0: for e in .0: if 'type' not in e._attrs: (e._name, e._cdata)continue)(elt)) def _update_ccard_livecontact(self, elt): pass def __cmp__(self, other): try: if other is self: return 0 return cmp((self.name, self.protocol), (other.name, other.protocol)) except: return -1 def pretty_profile(self): d = { } if self.remote_alias and self.alias != self.remote_alias: d[_('Display Name:')] = self.remote_alias pretty_profile = property(pretty_profile) class MSNSpaceElement(object): def __init__(self, elt): object.__init__(self) for attr in ('title', 'url', 'description', 'tooltip'): setattr(self, attr, str(getattr(elt, attr, '')).decode('utf-8')) self.last_check = yesterday() self.last_update = yesterday() def __repr__(self): res = [ '<%s ' % type(self).__name__] for attr in ('title', 'url', 'description', 'tooltip'): myval = getattr(self, attr) if myval: res.append('%s=%s, ' % (attr.capitalize(), myval)) continue res[-1] = res[-1][:-2] + '>' return ''.join(res) def __iter__(self): def attrs(): for attr in ('title', 'url', 'description', 'tooltip'): val = getattr(self, attr) if val: yield (attr, val) continue import itertools return itertools.chain(attrs(), iter(self.contents)) def pretty_profile(self, p = None): if not p: pass p = odict() p[self.title + ':'] = [ '\n', (self.url, self.description)] return p pretty_profile = property(pretty_profile) def to_tag(self): table = tag('table') tr = tag('tr') a = tag('a', href = self.url) a._add_child(tag('b', self.title + ':')) tr._add_child(a) tr._add_child(tag('td', self.description)) table._add_child(tr) return table class SpaceTitleElt(MSNSpaceElement): def to_tag(self): a = tag('a', href = self.url) a._add_child('b', self.title) return a def pretty_profile(self): return { } pretty_profile = property(pretty_profile) class GenericListElt(list, MSNSpaceElement): def __init__(self, elt): MSNSpaceElement.__init__(self, elt) []([], _[1]) def __repr__(self): return '<%s: %s>' % (type(self).__name__, list.__repr__(self)) def __iter__(self): return list.__iter__(self) def pretty_profile(self): return odict(MSNSpaceElement.pretty_profile.fget(self).items()) pretty_profile = property(pretty_profile) def to_tag(self): p = MSNSpaceElement.to_tag(self) for thing in self: p._add_child(thing.to_tag()) return p class MSNSpace(MSNSpaceElement): _name = 'MSN Space' def __init__(self, buddy, contact_card): MSNSpaceElement.__init__(self, contact_card) self.last_update = str(contact_card.lastUpdate) self.title = contact_card._attrs.get('displayName', buddy.name).strip().decode('utf-8') self.buddy = buddy self.dp_url = contact_card._attrs.get('displayPictureUrl', '') self.contents = [] for element in contact_card.elements: type_ = element['type'] cls = getattr(thismod, '%sElt' % type_, MSNSpaceElement) self.contents.append(cls(element)) def pretty_profile(self): p = odict() for thing in self.contents: p.update(thing.pretty_profile.items()) url = self.contents[0].url if not url and self.buddy.CID: url = 'http://spaces.live.com/Profile.aspx?cid=%s' % self.buddy.CID elif not self.buddy.CID: return p p['Profile URL:'] = [ '\n', (url, url)] return p pretty_profile = property(pretty_profile) def to_tag(self): p = tag('p') for thing in self.contents: p._add_child(thing.to_tag()) return p class GenericListEntryElt(MSNSpaceElement): def __init__(self, elt): MSNSpaceElement.__init__(self, elt) self.last_update = elt['lastUpdated'] self.title = str(elt.title).strip().decode('utf-8') def pretty_profile(self): return odict({ self.title: '\n' }) pretty_profile = property(pretty_profile) class MusicListElt(GenericListElt): def pretty_profile(self): songlist = [ x.pretty_profile for x in self ] songlist.insert(0, '\n') return odict({ 'Songs:': songlist }) pretty_profile = property(pretty_profile) class MusicListEntryElt(GenericListEntryElt): def __init__(self, elt): GenericListEntryElt.__init__(self, elt) self.artist = str(elt.artist).decode('utf-8') self.song = str(elt.song).decode('utf-8') def pretty_profile(self): return (self.url, _(u'%s by %s') % (self.song, self.artist + u'\n')) pretty_profile = property(pretty_profile) class BookListElt(GenericListElt): def to_tag(self): p = tag('p') p._add_child(tag('a', self.title, href = self.url)) for thing in self: p._add_child(thing.to_tag()) return p class BookListEntryElt(GenericListEntryElt): def to_tag(self): return tag('p', '%s<br />%s' % (self.title, self.description)) class BlogElt(GenericListElt): def to_tag(self): p = tag('p') for thing in self: p._add_child(thing.to_tag()) return p def pretty_profile(self): return []([ post.pretty_profile for post in self ]) pretty_profile = property(pretty_profile) class PostElt(GenericListEntryElt): def to_tag(self): link = tag('a', self.title, href = self.url) return tag('p', 'New post: %s<br />%s' % (link._to_xml(), self.description)) def pretty_profile(self): return (self.title + ':', [ '\n', (self.url, self.description)]) pretty_profile = property(pretty_profile) class AlbumElt(GenericListElt): def to_tag(self): p = tag('p') tr = tag('b', 'Photos Album:') for photo in self: tr._add_child(photo.to_tag()) p._add_child(tr) return p def pretty_profile(self): piclist = [ x.pretty_profile for x in self ] piclist.insert(0, '\n') return odict({ 'Photos:': piclist }) pretty_profile = property(pretty_profile) class PhotoElt(GenericListEntryElt): (WIDTH, HEIGHT) = (20, 20) def __init__(self, elt): GenericListEntryElt.__init__(self, elt) self.thumbnail_url = str(elt.thumbnailUrl) self.web_url = str(elt.webReadyUrl) self.album_name = str(elt.albumName).decode('utf-8') self.img_sm = None self.img_lg = None self.loadimages() def to_tag(self): a = tag('a', href = self.url) a._add_child(tag('img', src = self.web_url, alt = self.tooltip, width = self.WIDTH, height = self.HEIGHT)) return a def pretty_profile(self): pref = pref import common sz = pref('msn.spaces.photosize', 20) if self.img_sm is None: return (self.url, u'%s - %s' % (self.album_name, self.title + u'\n')) return dict(data = self.img_sm, alt = self.tooltip, height = sz, width = sz, href = self.url) pretty_profile = property(pretty_profile) def loadimages(self): try: self.img_sm = urlcacheopen(self.thumbnail_url) except: self.imb_sm = 'javascript' if self.img_sm and 'javascript' in self.img_sm: self.img_sm = None try: self.img_lg = urlcacheopen(self.web_url) except: self.img_lg = 'javascript' if self.img_lg and 'javascript' in self.img_lg: self.img_lg = None loadimages = threaded(loadimages) class MSNContact(contacts.Contact): _renderer = 'Contact' inherited_actions = [ MSNBuddy] def __init__(self, buddy, group_obj_or_id): group_id = getattr(group_obj_or_id, 'name', group_obj_or_id) contacts.Contact.__init__(self, buddy, (buddy.name, group_id)) def __repr__(self): return '<MSN' + contacts.Contact.__repr__(self)[4:] def block(self, *a, **k): return contacts.Contact.block(self, *a, **k) block = common.action(contacts.Contact._block_pred)(block) def unblock(self, *a, **k): return contacts.Contact.unblock(self, *a, **k) unblock = common.action(contacts.Contact._unblock_pred)(unblock) def from_mime(mime_info, email, msn, friendlyname = None): b = msn.get_buddy(email) if friendlyname: if not url_decode(friendlyname).decode('utf-8'): pass b.remote_alias = None info = to_storage(mime_info) for k, v in info.items(): k = k.replace(' ', '_').replace('-', '_').lower() setattr(b, k, v) b.info = dict(info.items()) return b def from_lst(msn, N, **kwargs): email = N kwargs = to_storage(kwargs) b = msn.get_buddy(email) if 'F' in kwargs: if not url_decode(kwargs['F']).decode('utf-8'): pass b.remote_alias = None if 'C' in kwargs: b.guid = msn.cid_class(kwargs['C']) return b CONTACT_CARD = '\n\n<contactCard>\n <storageAuthCache>\n 1pqFlR36RzjW-X1jmTbKjKRsUpCe4cq9KHls4whqQIXlnjXVMidNbandYSmy0QEqm17M7xLIb2Fvo\n </storageAuthCache>\n <elements returnedMatches="3" displayName="shaps" totalMatches="3" displayPictureUrl="http://shared.live.com/jdIfE-NNCwZHMseiLFdi12c3U3v1VRQA5Wr8zoyj4Q0IBYQYt0pq5GcGiVCgriAz-mQjoThX0wVn7RxL!igd-A/base/3379/Controls/img/ContactControl/WLXLarge_default.gif">\n <element type="SpaceTitle">\n <title>\n Steve\'s Space\n </title>\n <url>\n http://shaps776.spaces.live.com/?owner=1\n </url>\n <totalNewItems>\n 0\n </totalNewItems>\n </element>\n <element type="BookList">\n <subElement type="BookListEntry" lastUpdated="0001-01-01T00:00:00">\n <description>\n stuff for description\n </description>\n <title>\n book title 3\n </title>\n <tooltip>\n Title: book title 3\n Author: author\n Description: stuff for description\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Lists/cns!2DB0770EAE61F13!106?owner=1\n </url>\n </subElement>\n <subElement type="BookListEntry" lastUpdated="0001-01-01T00:00:00">\n <description>\n lkj lkj l\n </description>\n <title>\n book title 2\n </title>\n <tooltip>\n Title: book title 2Author: author 2Description: lkj lkj l\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Lists/cns!2DB0770EAE61F13!106?owner=1\n </url>\n </subElement>\n <title>\n Book List\n </title>\n <url>\n http://shaps776.spaces.live.com/Lists/cns!2DB0770EAE61F13!106?owner=1\n </url>\n <description>\n book title 3\n </description>\n <totalNewItems>\n 0\n </totalNewItems>\n </element>\n <element type="Album">\n <subElement type="Photo" lastUpdated="2007-04-17T09:35:32.31-07:00">\n <description>\n Photos\n </description>\n <title>\n 10.png\n </title>\n <tooltip>\n January 1710.png\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/photos/cns!2DB0770EAE61F13!138/cns!2DB0770EAE61F13!151?owner=1\n </url>\n <thumbnailUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxszOikmaP3r3dXbFG7ToyO0hMKW-WHHHJ2D9Lmff30X2Jo-2STreLVcNjaEogTUoBTZHMxhbwHv0ZBeHMwOnEdJcPytZWhE0nfg\n </thumbnailUrl>\n <webReadyUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxszOikmaP3r3dlq-_0irNxa_2G2Gzp9ZgHOfSTUGN79t1IYnjSY5DKTXfP4ADxmBKN0Z5m0I7P6TUjGRafqU4NPz05iaCqzwJRA\n </webReadyUrl>\n <albumName>\n January 17\n </albumName>\n </subElement>\n <subElement type="Photo" lastUpdated="2007-04-17T09:35:32.107-07:00">\n <description>\n Photos\n </description>\n <title>\n 9.gif\n </title>\n <tooltip>\n January 179.gif\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/photos/cns!2DB0770EAE61F13!138/cns!2DB0770EAE61F13!150?owner=1\n </url>\n <thumbnailUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxswE_zjzklXeXVqyaBoOfjid5rjfn8g0bSHcgQmQ5AoqTuNtwMzT-XNFSFv_IKj8mcZZ-ENJcOYB3XWJYb3U0wC4RSwlFUqeGfw\n </thumbnailUrl>\n <webReadyUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxswE_zjzklXeXVJfE1Gdeox-zkKou9QwXud_dSI32qXsAnPABY4K57fs1bpWbe7JSZdhHJwEQ0psi7lGPBDLpdW0_3sUHaRDjuA\n </webReadyUrl>\n <albumName>\n January 17\n </albumName>\n </subElement>\n <subElement type="Photo" lastUpdated="2007-04-17T09:35:31.967-07:00">\n <description>\n Photos\n </description>\n <title>\n 8.gif\n </title>\n <tooltip>\n January 178.gif\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/photos/cns!2DB0770EAE61F13!138/cns!2DB0770EAE61F13!149?owner=1\n </url>\n <thumbnailUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxs1s-Updfv0-X7Rk9c9exySfJ-2PozaK6BKKyP9v8DAcv5xxyZSZ0OK9wirfRd2yWEEX7VzZS2mvvBkUWbtz0VXbLead2Ybs5OA\n </thumbnailUrl>\n <webReadyUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxs1s-Updfv0-XLAU_ZUH4P33y-NaJII-4uupQ0uoxjOCQJwxrL6sA1Xa9X3mdKUNYrj95_CVyrr5QVP7BXWFFyd2avflir6OhOA\n </webReadyUrl>\n <albumName>\n January 17\n </albumName>\n </subElement>\n <subElement type="Photo" lastUpdated="2007-04-17T09:35:08.043-07:00">\n <description>\n Photos\n </description>\n <title>\n 7.png\n </title>\n <tooltip>\n January 177.png\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/photos/cns!2DB0770EAE61F13!138/cns!2DB0770EAE61F13!148?owner=1\n </url>\n <thumbnailUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxsyrdesm1gzDOdiW3uJUFNjo3H7f9H4uLtkj7u-akJEORhy2lLsKpM01wmbQvBUA-OEZdfQLdJi-NouMArPt5N0CW4nYHxW51UA\n </thumbnailUrl>\n <webReadyUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxsyrdesm1gzDO9TYtPpGT2JsdnYIUZw7Lo5-yTazqwfIGHa6vu-Ku9OIMA0gLptXjy6IMXfr-CV5cag2FJKcqo_rVuPRT2t_t7w\n </webReadyUrl>\n <albumName>\n January 17\n </albumName>\n </subElement>\n <subElement type="Photo" lastUpdated="2007-04-17T09:35:07.933-07:00">\n <description>\n Photos\n </description>\n <title>\n 6.jpg\n </title>\n <tooltip>\n January 176.jpg\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/photos/cns!2DB0770EAE61F13!138/cns!2DB0770EAE61F13!147?owner=1\n </url>\n <thumbnailUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxs-wyD9TggUJ_4XM7tDqJ6CINNBLXvtT4Lfwr7ikxskuBzMQNerpK-oV8CvyWk9BbashoZg1H9afsvyl576NJp4I0FWfrI4hwBw\n </thumbnailUrl>\n <webReadyUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxs-wyD9TggUJ_C3BxBY1m6WsjbKXjpxDULsHHHEg8yAl2WLKDzSqb99OBxXaSetCdU-p8o6ScLb807p2QFAWr4gtH6OvBof2EBg\n </webReadyUrl>\n <albumName>\n January 17\n </albumName>\n </subElement>\n <subElement type="Photo" lastUpdated="2007-04-17T09:35:07.81-07:00">\n <description>\n Photos\n </description>\n <title>\n 5.jpg\n </title>\n <tooltip>\n January 175.jpg\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/photos/cns!2DB0770EAE61F13!138/cns!2DB0770EAE61F13!146?owner=1\n </url>\n <thumbnailUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxs49JgAmSpKyqet5yR2Upi4Nn_X5ewL5gr6Tst7QFxHUmmjxQJpMpldLBUCWxs5dXLddQfHtjnSJTjycfX0vvZYvb9vVzlON9OA\n </thumbnailUrl>\n <webReadyUrl>\n http://blufiles.storage.msn.com/x1pPHu2K6HCG6qh_ATHNyPxs49JgAmSpKyq-H9kk6kls9jjKFGLEr9AWb3NdQAxCcI6ta_72H6Ct25Dzjm1lkz7_xgUUuKboUy37TR0hveNy5ZRjhJ1eMUzcw\n </webReadyUrl>\n <albumName>\n January 17\n </albumName>\n </subElement>\n <title>\n Photos:\n </title>\n <url>\n http://shaps776.spaces.live.com/Photos/?owner=1\n </url>\n <totalNewItems>\n 0\n </totalNewItems>\n </element>\n <element type="Blog">\n <subElement type="Post" lastUpdated="2007-01-16T13:55:01.013-08:00">\n <description>\n sfljks dflkjsdflkjsdflkjs dflkjsad flks jdaflsa dkjflsadkfjsadlfkj\n </description>\n <title>\n NEWNEWNEW\n </title>\n <tooltip>\n sfljks dflkjsdflkjsdflkjs dflkjsad flks jdaflsa dkjflsadkfjsadlfkj\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Blog/cns!2DB0770EAE61F13!130.entry?owner=1\n </url>\n </subElement>\n <title>\n Blog:\n </title>\n <url>\n http://shaps776.spaces.live.com/?owner=1\n </url>\n <totalNewItems>\n 0\n </totalNewItems>\n </element>\n <element type="Profile">\n <subElement type="GeneralProfile" lastUpdated="2007-01-16T09:01:51.533-08:00">\n <description />\n <title>\n General profile info updated\n </title>\n <tooltip>\n This person has recently added or updated General profile information.\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view\n </url>\n </subElement>\n <subElement type="PublicProfile" lastUpdated="2006-12-21T16:06:47.47-08:00">\n <description />\n <title>\n Public profile info updated\n </title>\n <tooltip>\n This person has recently added or updated Public profile information.\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view\n </url>\n </subElement>\n <subElement type="SocialProfile" lastUpdated="2006-05-31T09:54:52.59-07:00">\n <description />\n <title>\n Social profile info updated\n </title>\n <tooltip>\n This person has recently added or updated Social profile information.\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view\n </url>\n </subElement>\n <title>\n Profile\n </title>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view\n </url>\n <description>\n General profile info updated\n </description>\n <totalNewItems>\n 3\n </totalNewItems>\n </element>\n <element type="LiveContact">\n <subElement type="ProfessionalContactProfile" lastUpdated="2006-12-21T16:06:47.47-08:00">\n <description />\n <title>\n Business contact info updated\n </title>\n <tooltip>\n This person has recently added or updated Business contact information.\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view&mode=activecontacts\n </url>\n </subElement>\n <subElement type="PersonalContactProfile" lastUpdated="2006-12-21T16:06:47.47-08:00">\n <description />\n <title>\n Personal contact info updated\n </title>\n <tooltip>\n This person has recently added or updated Personal contact information.\n </tooltip>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view&mode=activecontacts\n </url>\n </subElement>\n <title>\n Contact Info\n </title>\n <url>\n http://shaps776.spaces.live.com/Profile.aspx?cid=205766389534170899&mkt=en-us&action=view&mode=activecontacts\n </url>\n <description>\n Business contact info updated\n </description>\n <totalNewItems>\n 2\n </totalNewItems>\n </element>\n </elements>\n <lastUpdate>\n 2007-04-18T08:20:01.167-07:00\n </lastUpdate>\n <theme>\n <name>\n personalspacegree\n </name>\n <titleBar foreground="333333" fontFace="" background="f4fbf7" />\n <clientArea foreground="444444" backgroundImage="http://shared.live.com/jdIfE-NNCwb0XZTwVBd6PpCWk!2k7FEfmc0OX5OC0rZ-I0WjzyccY5aYuUiTkMo2blaFQRxUooU/personalspacegree/3379/img/green_card_bkgd.gif" fontFace="" background="FFFFFF" />\n <toolbar foreground="333333" fontFace="" background="f4fbf7" />\n <border topLeftImage="http://sc1.sclive.net/11.01.3810.0000/Web/Contacts/images/card_ul.gif" bottomLeftImage="http://sc2.sclive.net/11.01.3810.0000/Web/Contacts/images/card_ll.gif" bottomRightImage="http://sc4.sclive.net/11.01.3810.0000/Web/Contacts/images/card_lr.gif" outline="7F7F7F" topRightImage="http://sc3.sclive.net/11.01.3810.0000/Web/Contacts/images/card_ur.gif" />\n </theme>\n <liveTheme>\n <themeName>\n personalspacegree\n </themeName>\n <head backgroundImage="http://shared.live.com/jdIfE-NNCwb0XZTwVBd6PpCWk!2k7FEfmc0OX5OC0rZ-I0WjzyccY5aYuUiTkMo2blaFQRxUooU/personalspacegree/3379/img/SmallBannerImage.jpg" textColor="333333" linkColor="006629" backgroundColor="f4fbf7" />\n <body accordionHoverColor="aad2ba" secondaryLinkColor="7F7F7F" dividerColor="8ed4ab" backgroundImage="" backgroundColor="f4fbf7" linkColor="006629" textColor="333333" />\n <actions linkColor="333333" backgroundColor="f4fbf7" />\n </liveTheme>\n</contactCard>\n'.strip().replace('&', '&') if __name__ == '__main__': b = Storage(name = 'shaps776@hotmail.com') card = MSNSpace(b, tag(CONTACT_CARD)) print card.to_tag()._to_xml()